package edu.ynu.se.xiecheng.achitectureclass.service;

import edu.ynu.se.xiecheng.achitectureclass.common.dto.TokenResponseDTO;
import edu.ynu.se.xiecheng.achitectureclass.dto.SensorDataDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class FboxService {
    private static final String CLIENT_ID = "68db2e8bda8d47b5b5db7eaf71c7dcdd";
    private static final String CLIENT_SECRET = "76dc724c95004acab25482d344dab407";
    
    @Autowired
    private RestTemplate restTemplate;

    private String cachedToken = null;
    private long tokenExpireTime = 0;

    public TokenResponseDTO getToken() {
        // 检查缓存的token是否还有效（提前5分钟刷新）
        if (isTokenValid()) {
            return createCachedTokenResponse();
        }
        return requestNewToken();
    }

    private boolean isTokenValid() {
        return cachedToken != null && System.currentTimeMillis() < tokenExpireTime - 300_000L;
    }

    private TokenResponseDTO createCachedTokenResponse() {
        TokenResponseDTO cachedResponse = new TokenResponseDTO();
        cachedResponse.setAccessToken(cachedToken);
        cachedResponse.setExpiresIn(7200);
        cachedResponse.setTokenType("Bearer");
        cachedResponse.setScope("fbox");
        return cachedResponse;
    }

    private TokenResponseDTO requestNewToken() {
        String url = "https://fbox360.com/idserver/core/connect/token";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("scope", "fbox");
        map.add("client_id", CLIENT_ID);
        map.add("client_secret", CLIENT_SECRET);
        map.add("grant_type", "client_credentials");

        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

        try {
            ResponseEntity<TokenResponseDTO> response = restTemplate.postForEntity(
                    url, request, TokenResponseDTO.class);

            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                TokenResponseDTO tokenResponse = response.getBody();
                updateTokenCache(tokenResponse);
                return tokenResponse;
            }
            throw new RuntimeException("Failed to get token: " + response.getStatusCode());
        } catch (Exception e) {
            throw new RuntimeException("Failed to get token: " + e.getMessage());
        }
    }

    private void updateTokenCache(TokenResponseDTO tokenResponse) {
        cachedToken = tokenResponse.getAccessToken();
        long expiresInMillis = (long) (tokenResponse.getExpiresIn() - 300) * 1000L;
        tokenExpireTime = System.currentTimeMillis() + expiresInMillis;
    }

    public List<SensorDataDTO> getSensorData(String boxNo, List<String> sensorIds) {
        try {
            String url = "https://fbox360.com/api/v2/dmon/value/get?boxNo=" + boxNo;
            
            // 获取token
            TokenResponseDTO tokenResponse = getToken();
            
            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setBearerAuth(tokenResponse.getAccessToken());

            // 设置请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("ids", sensorIds);

            // 创建请求实体
            HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);

            // 发送POST请求
            ResponseEntity<List<SensorDataDTO>> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                request,
                new ParameterizedTypeReference<List<SensorDataDTO>>() {}
            );

            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                List<SensorDataDTO> sensorDataList = response.getBody();
                
                // 处理特殊传感器数据
                for (SensorDataDTO data : sensorDataList) {
                    // 空气温度和空气湿度需要除以10
                    if (data.getId().equals("327061375295689611") ||    // 空气温度
                        data.getId().equals("327061375295689612")) {    // 空气湿度
                        data.setValue(data.getValue() / 10.0);
                    }
                }
                
                return sensorDataList;
            }
            
            throw new RuntimeException("Failed to get sensor data: " + response.getStatusCode());
        } catch (Exception e) {
            throw new RuntimeException("Failed to get sensor data: " + e.getMessage());
        }
    }
} 